package com.ae.shield.common.block.tile;

import com.ae.shield.api.IButtonHandler;
import com.ae.shield.common.capability.energy.BlockEnergyStorage;
import com.ae.shield.common.gui.container.NanoRobotProgrammerContainer;
import com.ae.shield.common.items.EffectStorageItem;
import com.ae.shield.common.items.shieldFittings.makers.NanoRobot;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.play.server.SUpdateTileEntityPacket;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.energy.IEnergyStorage;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class NanoRobotProgrammerTile extends TileEntity implements INamedContainerProvider, ITickableTileEntity, IButtonHandler {
    protected ItemStackHandler inventory = new ItemStackHandler(5);
    private final LazyOptional<IItemHandler> itemCap = LazyOptional.of(() -> inventory);
    protected BlockEnergyStorage energy = new BlockEnergyStorage(10000);
    private final LazyOptional<IEnergyStorage> energyCap = LazyOptional.of(() -> energy);

    public NanoRobotProgrammerTile() {
        super(TileEntityList.NANO_ROBOT_PROGRAMMER_TILE.get());
    }

    @Override
    public void tick() {
        if (!world.isRemote) {
            if (world.getGameTime() % 20 == 0) {
                world.notifyBlockUpdate(pos, getBlockState(), getBlockState(), Constants.BlockFlags.BLOCK_UPDATE);
            }
        }
    }

    @Nullable
    @Override
    public SUpdateTileEntityPacket getUpdatePacket() {
        return new SUpdateTileEntityPacket(pos, 1, getUpdateTag());
    }

    @Override
    public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) {
        handleUpdateTag(world.getBlockState(pkt.getPos()), pkt.getNbtCompound());
    }

    @Nonnull
    @Override
    public CompoundNBT getUpdateTag() {
        return write(new CompoundNBT());
    }

    @Override
    public void handleUpdateTag(BlockState state, CompoundNBT tag) {
        super.handleUpdateTag(state, tag);
    }

    @Nonnull
    @Override
    public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
        String capName = cap.getName();
        switch (capName.substring(capName.lastIndexOf(".") + 1)) {
            case "IItemHandler":
                return itemCap.cast();
            case "IEnergyStorage":
                return energyCap.cast();
            default:
                return super.getCapability(cap, side);
        }
    }

    @Nonnull
    @Override
    public ITextComponent getDisplayName() {
        return new TranslationTextComponent("container.aeshield.nano_robot_programmer");
    }

    @Nullable
    @Override
    public Container createMenu(int id, @Nonnull PlayerInventory playerInventory, @Nonnull PlayerEntity playerEntity) {
        return new NanoRobotProgrammerContainer(id, playerInventory, pos);
    }

    public IItemHandler getInventory() {
        return inventory;
    }

    public IEnergyStorage getEnergy() {
        return energy;
    }

    @Override
    public void onButtonPressed(int button) {
        ItemStack stack = inventory.getStackInSlot(0);
        Item item = stack.getItem();

        if (!(item instanceof NanoRobot)) {
            return;
        }

        NanoRobot nanoRobot = (NanoRobot) item;
        for (int i = 1; i < inventory.getSlots(); i++) {
            ItemStack stackInSlot = inventory.getStackInSlot(i);
            if (stackInSlot.isEmpty() || !(stackInSlot.getItem() instanceof EffectStorageItem)) {
                continue;
            }

            if (energy.extractEnergy(300, true) < 300) {
                break;
            }

            nanoRobot.writeEffect(stack, ((EffectStorageItem) stackInSlot.getItem()).readPotionNbt(stackInSlot), i - 1);
            inventory.extractItem(i, 1, false);
            energy.extractEnergy(300, false);
        }
    }

    @Nonnull
    @Override
    public CompoundNBT write(@Nonnull CompoundNBT compound) {
        compound = super.write(compound);
        compound.put("Inventory", inventory.serializeNBT());
        compound.putInt("Energy", energy.getEnergyStored());
        return compound;
    }

    @Override
    public void read(@Nonnull BlockState state, @Nonnull CompoundNBT nbt) {
        super.read(state, nbt);
        inventory.deserializeNBT(nbt.getCompound("Inventory"));
        energy.setEnergy(nbt.getInt("Energy"));
    }
}
